#ifndef __KERN_MM_VMM_H__
#define __KERN_MM_VMM_H__

#include <defs.h>
#include <list.h>
#include <memlayout.h>
#include <sync.h>

//pre define
struct mm_struct;

// the virtual continuous memory area(vma), [vm_start, vm_end), 
// addr belong to a vma means  vma.vm_start<= addr <vma.vm_end 
//lab3新增的数据结构
struct vma_struct {
    struct mm_struct *vm_mm; //虚拟内存空间属于的PDE 
    uintptr_t vm_start;      // 连续地址的虚拟内存空间的起始位置     
    uintptr_t vm_end;        // 连续地址的虚拟内存空间的结束位置
    uint32_t vm_flags;       //虚拟空间的属性（读/写/可执行）
    list_entry_t list_link;  //双向链表，从小到大将虚拟内存空间连起来
};

#define le2vma(le, member)                  \
    to_struct((le), struct vma_struct, member)


//vm_flags表示虚拟内存空间属性
#define VM_READ                 0x00000001    //只读
#define VM_WRITE                0x00000002    //可读写
#define VM_EXEC                 0x00000004    //可执行

//描述一个PDE的虚拟地址空间,一个PDE中有多个vma结构
struct mm_struct {
    list_entry_t mmap_list;        //双向链表头，链接了所有属于同一页目录表的虚拟内存空间
    struct vma_struct *mmap_cache; //指向当前正在使用的虚拟内存空间
    pde_t *pgdir;                  //mm_struct数据结构所维护的页表
    int map_count;                 //记录mmap_list 里面链接的 vma_struct的个数
    void *sm_priv;                 //指向用来链接记录页访问情况的链表头（用于置换算法）
};

struct vma_struct *find_vma(struct mm_struct *mm, uintptr_t addr);//根据mm以及addr找到vma ,找到的vma满足(vma->vm_start <= addr <= vma_vm_end)
struct vma_struct *vma_create(uintptr_t vm_start, uintptr_t vm_end, uint32_t vm_flags);// vma的创建并初始化，根据参数vm_start、vm_end、vm_flags完成初始化
void insert_vma_struct(struct mm_struct *mm, struct vma_struct *vma);//向mm的mmap_list的插入一个vma，按地址插入合适位置

struct mm_struct *mm_create(void);//创一个mm_struct并初始化
void mm_destroy(struct mm_struct *mm);//删除一个mm struct

void vmm_init(void);

int do_pgfault(struct mm_struct *mm, uint32_t error_code, uintptr_t addr);

extern volatile unsigned int pgfault_num;
extern struct mm_struct *check_mm_struct;
#endif /* !__KERN_MM_VMM_H__ */

